package cn.com.zero.sample.trade.customer.controller;

import cn.com.zero.file.client.MinioTemplate;
import cn.com.zero.file.constants.FileUploadConstant;
import cn.com.zero.file.service.IFileService;
import cn.com.zero.file.util.FileUtil;
import cn.com.zero.file.vo.FileInfo;
import org.apache.commons.io.FilenameUtils;
import org.apache.dubbo.common.utils.MD5Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;

/**
 * @author liuxh
 * @version 1.0.0
 * @Description 文件接口示例-minio
 * @createTime 2022/9/20 14:58
 */
@RestController
@RequestMapping("/file/minio")
@ConditionalOnProperty(name = "zero.file.type", havingValue = FileUploadConstant.FILE_TYPE_MINIO)
public class FileController {
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    private IFileService fileService;
    private MinioTemplate minioTemplate;

    @Resource
    public void setMinioTemplate(MinioTemplate minioTemplate) {
        this.minioTemplate = minioTemplate;
    }

    @Resource
    public void setFileService(IFileService fileService) {
        this.fileService = fileService;
    }


    // 文件上传
    @PostMapping("/upload")
    public void uploadPicture(@RequestParam(value = "multipartFile") MultipartFile multipartFile) {
        String relativePath = "public/pic/";
        FileInfo fileInfo = fileService.upload(multipartFile, relativePath);
        log.info("文件上传完成,详细信息：{}", fileInfo);
        //  直接通过URL下载文件,URL参考： http://172.18.2.105:9000/minio-test-custom/public/pic/e29e3a1dd2a1405eaa43aea5a23a47c9.jpg
    }

    // 文件上传到私有存储桶
    @PostMapping("/uploadPrivate")
    public void uploadPrivatePicture(@RequestParam(value = "multipartFile") MultipartFile multipartFile) {
        String relativePath = "test/pic/";
        FileInfo fileInfo = fileService.upload(multipartFile, MinioTemplate.BUCKET_DEFAULT_PRIVATE, relativePath);
        log.info("文件上传完成,详细信息：{}", fileInfo);

        // 下载方式： 从服务端下载， 或者获取限时签名URL
    }

    // 压缩并上传图片 压缩宽为100px 高为：100px
    @PostMapping("/uploadCompress")
    public void uploadCompress(@RequestParam(value = "multipartFile") MultipartFile multipartFile) {
        String relativePath = "test/pic/";
        FileInfo fileInfo = fileService.uploadImage(multipartFile, MinioTemplate.BUCKET_DEFAULT, relativePath, 100, 100);
        log.info("文件上传完成,详细信息：{}", fileInfo);
    }

    // 删除文件
    @DeleteMapping("/delete")
    public void delete(@RequestParam("relativeFilePath") String relativeFilePath) {
        if (fileService.isExist(relativeFilePath)) {
            log.info("文件[{}]存在，开始删除文件。。。", relativeFilePath);
            fileService.delete(relativeFilePath);// 可以不判断文件是否存在
            log.info("文件[{}]存在，删除文件完成。。。", relativeFilePath);
        } else {
            log.info("文件[{}]不存在，删除失败", relativeFilePath);
        }
    }

    // 下载私有文件
    @PostMapping("/download")
    public org.springframework.core.io.Resource download(@RequestParam("relativeFilePath") String relativeFilePath) {
        return fileService.downloadFile(MinioTemplate.BUCKET_DEFAULT_PRIVATE, relativeFilePath);
    }

    // 下载私有文件
    @PostMapping("/download2")
    public String download2(@RequestParam("relativeFilePath") String relativeFilePath) {
        return fileService.downloadFileToBase64(MinioTemplate.BUCKET_DEFAULT_PRIVATE, relativeFilePath);
    }


    /**
     * 大文件分片上传
     *
     * @param file     分片文件
     * @param index    分片下标
     * @param fileName 原始文件名
     */
    @PostMapping(value = "/chunkUpload")
    public void chunkUpload(@RequestParam(value = "file") MultipartFile file, @RequestParam("index") int index, @RequestParam("fileName") String fileName) {
        String tempBucket = new MD5Utils().getMd5(fileName);
        minioTemplate.chunkUpload(tempBucket, index, file);
        log.info("大文件上传，上传分片[{}]到临时存储桶[{}]成功", index, tempBucket);
    }


    /**
     * 文件合并
     *
     * @param shardCount 分片总数
     * @param fileName   实际文件名
     * @param tempBucket 临时存储桶
     */
    @GetMapping(value = "/merge")
    public void merge(@RequestParam("shardCount") Integer shardCount, @RequestParam("fileName") String fileName, @RequestParam("tempBucket") String tempBucket) {

        String extension = FilenameUtils.getExtension(fileName);
        String relativePath = "test/video/";

        String relativeFilePath = FileUtil.getRelativeFilePath(extension, relativePath);

        FileInfo fileInfo = minioTemplate.merge(tempBucket, shardCount, MinioTemplate.BUCKET_DEFAULT, relativeFilePath);

        log.info("大文件上传完成,详细信息：{}", fileInfo);
    }

    /**
     * 将大文件文件分片为小文件（模拟测试用）
     *
     * @param f 文件  例如：Wildlife.wmv
     * @throws IOException 异常
     */
    public static void splitFile(File f) throws IOException {
        int partCounter = 1;

        int sizeOfFiles = 1024 * 1024 * 5;// 每个小文件最大为5MB
        byte[] buffer = new byte[sizeOfFiles];

        String extension = FilenameUtils.getExtension(f.getName());
        String fileName = FilenameUtils.getBaseName(f.getName());

        //分片
        try (FileInputStream fis = new FileInputStream(f);
             BufferedInputStream bis = new BufferedInputStream(fis)) {

            int bytesAmount = 0;
            while ((bytesAmount = bis.read(buffer)) > 0) {
                //构建小文件的新文件名  例如： Wildlife001.wmv 、Wildlife002.wmv
                String filePartName = String.format("%s%03d.%s", fileName, partCounter++, extension);

                File newFile = new File(f.getParent(), filePartName);
                try (FileOutputStream out = new FileOutputStream(newFile)) {
                    out.write(buffer, 0, bytesAmount);
                }
            }
        }
    }

}
